<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <meta name="author" content="Mouse0w0">
  
  <link rel="shortcut icon" href="../img/favicon.ico">
  <title>回顾HUD - NanoVG - Lwjglbook中文翻译</title>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700" />

  <link rel="stylesheet" href="../css/theme.css" />
  <link rel="stylesheet" href="../css/theme_extra.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
  
  <script>
    // Current page data
    var mkdocs_page_name = "\u56de\u987eHUD - NanoVG";
    var mkdocs_page_input_path = "24-hud-revisited.md";
    var mkdocs_page_url = null;
  </script>
  
  <script src="../js/jquery-2.1.1.min.js" defer></script>
  <script src="../js/modernizr-2.8.3.min.js" defer></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script> 
  
</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
    <div class="wy-side-scroll">
      <div class="wy-side-nav-search">
        <a href=".." class="icon icon-home"> Lwjglbook中文翻译</a>
        <div role="search">
  <form id ="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" title="Type search term here" />
  </form>
</div>
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../01-first-steps/">事前准备</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../02-the-game-loop/">游戏循环</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../03-a-brief-about-coordinates/">坐标简介</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../04-rendering/">渲染</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../05-more-on-rendering/">渲染补充</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../06-transformations/">变换</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../07-textures/">纹理</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../08-camera/">摄像机</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../09-loading-more-complex-models/">加载更复杂的模型</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../10-let-there-be-light/">要有光</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../11-let-there-be-even-more-light/">要有更多的光</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../12-game-hud/">游戏HUD</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../13-sky-box-and-some-optimizations/">天空盒与一些优化</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../14-height-maps/">高度图</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../15-terrain-collisions/">地形碰撞</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../16-fog/">雾</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../17-normal-mapping/">法线贴图</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../18-shadows/">阴影</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../19-animations/">动画</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../20-particles/">粒子</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../21-instanced-rendering/">实例化渲染</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../22-audio/">音效</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../23-3d-object-picking/">三维物体选取</a>
                    </li>
                </ul>
                <ul class="current">
                    <li class="toctree-l1 current"><a class="reference internal current" href="./">回顾HUD - NanoVG</a>
    <ul class="current">
    </ul>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../25-optimizations-frustum-culling/">优化 - 截锥剔除</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../26-cascaded-shadow-maps/">级联阴影映射</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../27-assimp/">Assimp库</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../28-deferred-shading/">延迟着色法</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../a01-opengl-debugging/">附录 A - OpenGL调试</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../glossary/">术语表</a>
                    </li>
                </ul>
      </div>
    </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="..">Lwjglbook中文翻译</a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="..">Docs</a> &raquo;</li>
    
      
    
    <li>回顾HUD - NanoVG</li>
    <li class="wy-breadcrumbs-aside">
      
        <a href="https://github.com/Mouse0w0/lwjglbook-CN-Translation/edit/master/docs/24-hud-revisited.md"
          class="icon icon-github"> Edit on GitHub</a>
      
    </li>
  </ul>
  
  <hr/>
</div>
          <div role="main">
            <div class="section">
              
                <h1 id="hud-nanovghud-revisited-nanovg">回顾HUD - NanoVG（HUD Revisited - NanoVG）</h1>
<p>在此前的章节中，我们讲解了如何使用正交投影在场景顶部创建一个HUD以渲染图形和纹理。在本章中，我们将学习如何使用<a href="https://github.com/memononen/nanovg">NanoVG</a>库来渲染抗锯齿矢量图形，从而以简单的方式创建更复杂的HUD。</p>
<p>你可以使用许多其他库来完成此事，例如<a href="https://github.com/nifty-gui/nifty-gui">Nifty GUI</a>，<a href="https://github.com/vurtun/nuklear">Nuklear</a>等。在本章是，我们将重点介绍NanoVG，因为它使用起来非常简单，但是如果你希望开发可与按钮、菜单和窗口交互的复杂GUI，那你可能需要的是<a href="https://github.com/nifty-gui/nifty-gui">Nifty GUI</a>。</p>
<p>使用<a href="https://github.com/memononen/nanovg">NanoVG</a>首先是要在<code>pom.xml</code>文件中添加依赖项（一个是用于编译时所需的依赖项，另一个是用于运行时所需的本地代码）：</p>
<pre><code class="xml">...
&lt;dependency&gt;
    &lt;groupId&gt;org.lwjgl&lt;/groupId&gt;
    &lt;artifactId&gt;lwjgl-nanovg&lt;/artifactId&gt;
    &lt;version&gt;${lwjgl.version}&lt;/version&gt;
&lt;/dependency&gt;
...
&lt;dependency&gt;
    &lt;groupId&gt;org.lwjgl&lt;/groupId&gt;
    &lt;artifactId&gt;lwjgl-nanovg&lt;/artifactId&gt;
    &lt;version&gt;${lwjgl.version}&lt;/version&gt;
    &lt;classifier&gt;${native.target}&lt;/classifier&gt;
    &lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
</code></pre>

<p>在开始使用<a href="https://github.com/memononen/nanovg">NanoVG</a>之前，我们必须在OpenGL设置一些东西，以便示例能够正常工作。我们需要启用对模板测试（Stencil Test）的支持。到目前为止，我们已经讲解了颜色和深度缓冲区，但我们没有提到模板缓冲区。该缓冲区为用于控制应绘制哪些像素的每个像素储存一个值（整数），用于根据储存的值以屏蔽或放弃绘图区域。例如，它可以用来以一种简单的方式切割场景的某些部分。我们通过将此行添加到<code>Window</code>类中来启用模板测试（在启用深度测试之后）：</p>
<pre><code class="java">glEnable(GL_STENCIL_TEST);
</code></pre>

<p>因为我们使用的是另一个缓冲区，所以在每次渲染调用之前，我们还必须注意删除它的值。因此，我们需要修改<code>Renderer</code>类的<code>clear</code>方法：</p>
<pre><code class="java">public void clear() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
</code></pre>

<p>我们还将添加一个新的窗口选项来激活抗锯齿（Anti-aliasing）。因此，在<code>Window</code>类中，我们将通过如下方式启用它：</p>
<pre><code class="java">if (opts.antialiasing) {
    glfwWindowHint(GLFW_SAMPLES, 4);
}
</code></pre>

<p>现在我们可以使用<a href="https://github.com/memononen/nanovg">NanoVG</a>库了。我们要做的第一件事就是删掉我们创建的HUD代码，即着色器，<code>IHud</code>接口，<code>Renderer</code>类中的HUD渲染方法等。你可以在源代码中查看。</p>
<p>在此情况下，新的<code>Hud</code>类将负责其渲染，因此我们不需要将其委托给<code>Renderer</code>类。让我们先定义这个类，它将有一个<code>init</code>方法来设置库和构建HUD所需要的资源。方法定义如下：</p>
<pre><code class="java">public void init(Window window) throws Exception {
    this.vg = window.getOptions().antialiasing ? nvgCreate(NVG_ANTIALIAS | NVG_STENCIL_STROKES) : nvgCreate(NVG_STENCIL_STROKES);
    if (this.vg == NULL) {
        throw new Exception(&quot;Could not init nanovg&quot;);
    }

    fontBuffer = Utils.ioResourceToByteBuffer(&quot;/fonts/OpenSans-Bold.ttf&quot;, 150 * 1024);
    int font = nvgCreateFontMem(vg, FONT_NAME, fontBuffer, 0);
    if (font == -1) {
        throw new Exception(&quot;Could not add font&quot;);
    }
    colour = NVGColor.create();

    posx = MemoryUtil.memAllocDouble(1);
    posy = MemoryUtil.memAllocDouble(1);

    counter = 0;
}
</code></pre>

<p>我们首先要做的是创建一个NanoVG上下文。在本例中，我们使用的是OpenGL3.0后端，因此我们引用的是<code>org.lwjgl.nanovg.NanoVGGL3</code>命名空间。如果抗锯齿被启用，我们将设置<code>NVG_ANTIALIAS</code>标志。</p>
<p>接下来，我们使用此前加载到<code>ByteBuffer</code>中的TrueType字体来创建字体。我们为它指定一个名词，以便稍后在渲染文本时使用它。关于这点，一件很重要的事情是用于加载字体的<code>ByteBuffer</code>必须在使用字体时储存在内存中。也就是说，它不能被回收，否则你将得到一个不错的核心崩溃。这就是将它储存为类属性的原因。</p>
<p>然后，我们创建一个颜色实例和一些有用的变量，这些变量将在渲染时使用。在初始化渲染之前，在游戏初始化方法中调用该方法：</p>
<pre><code class="java">@Override
public void init(Window window) throws Exception {
    hud.init(window);
    renderer.init(window);
    ...
</code></pre>

<p><code>Hud</code>类还定义了一个渲染方法，该方法应在渲染场景后调用，以便在其上绘制Hud。</p>
<pre><code class="java">@Override
public void render(Window window) {
    renderer.render(window, camera, scene);
    hud.render(window);
}
</code></pre>

<p>Hud类的<code>render</code>方法的开头如下所示：</p>
<pre><code class="java">public void render(Window window) {
    nvgBeginFrame(vg, window.getWidth(), window.getHeight(), 1);
</code></pre>

<p>首先必须要做的第一件事是调用<code>nvgBeginFrame</code>方法。所有NanoVG渲染操作都必须保护在<code>nvgBeginFrame</code>和<code>nvgEndFrame</code>调用之间。<code>nvgBeginFrame</code>接受以下参数：</p>
<ul>
<li>NanoVG环境</li>
<li>要渲染的窗口的大小（宽度和高度）。</li>
<li>像素比。如果需要支持Hi-DPI，可以修改此值。对于本例，我们只将其设置为1。</li>
</ul>
<p>然后我们创建了几个占据整个屏幕的色带。第一条是这样绘制的：</p>
<pre><code class="java">// 上色带
nvgBeginPath(vg);
nvgRect(vg, 0, window.getHeight() - 100, window.getWidth(), 50);
nvgFillColor(vg, rgba(0x23, 0xa1, 0xf1, 200, colour));
nvgFill(vg);
</code></pre>

<p>渲染图形时，应调用的第一个方法是<code>nvgBeginPath</code>，它指示NanoVG开始绘制新图形。然后定义要绘制的内容，一个矩形，填充颜色并通过调用<code>nvgFill</code>绘制它。</p>
<p>你可以查看源代码的其他部分，以了解其余图形是如何绘制的。当渲染文本是，不需要在渲染前调用<code>nvgBeginPath</code>。</p>
<p>完成所有图形的绘制后，我们只需要调用<code>nvgEndFrame</code>来结束渲染，但在离开方法之前还有一件重要的事情要做。我们必须恢复OpenGL状态，NanoVG修改OpenGL以执行其操作，如果状态未正确还原，你可能会看到场景没有正确渲染，甚至被擦除。因此，我们需要恢复渲染所需的相关OpenGL状态。这是委派到<code>Window</code>类中的：</p>
<pre><code class="java">// 还原状态
window.restoreState();
</code></pre>

<p>方法的定义如下：</p>
<pre><code class="java">public void restoreState() {
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    if (opts.cullFace) {
        glEnable(GL_CULL_FACE);
        glCullFace(GL_BACK);
    }
}
</code></pre>

<p>这就完事了（除了一些其它的清理方法），代码完成了。当你运行示例时，你将得到如下结果：</p>
<p><img alt="Hud" src="../_static/24/hud.png" /></p>
              
            </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="../25-optimizations-frustum-culling/" class="btn btn-neutral float-right" title="优化 - 截锥剔除">Next <span class="icon icon-circle-arrow-right"></span></a>
      
      
        <a href="../23-3d-object-picking/" class="btn btn-neutral" title="三维物体选取"><span class="icon icon-circle-arrow-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <!-- Copyright etc -->
    
      <p>2019, Mouse0w0</p>
    
  </div>

  Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
      
        </div>
      </div>

    </section>

  </div>

  <div class="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
      
          <a href="https://github.com/Mouse0w0/lwjglbook-CN-Translation/" class="fa fa-github" style="float: left; color: #fcfcfc"> GitHub</a>
      
      
        <span><a href="../23-3d-object-picking/" style="color: #fcfcfc;">&laquo; Previous</a></span>
      
      
        <span style="margin-left: 15px"><a href="../25-optimizations-frustum-culling/" style="color: #fcfcfc">Next &raquo;</a></span>
      
    </span>
</div>
    <script>var base_url = '..';</script>
    <script src="../js/theme.js" defer></script>
      <script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" defer></script>
      <script src="../search/main.js" defer></script>
    <script defer>
        window.onload = function () {
            SphinxRtdTheme.Navigation.enable(true);
        };
    </script>

</body>
</html>
